﻿// Version posterior mejorada/simplificada a arKristal_v1.02

// Version 2.0

package motor.colision {
	
	import flash.display.*;
	import flash.events.*;
	import flash.net.*;
	import flash.utils.*;
	
	import flash.filters.*;
	
	
	public class Cuerpo extends EventDispatcher
	{
		
		public static const EVENTO_COLISION:String = "EVENTO_COLISION";
		//public static const EVENTO_ANIMAR  :String = "EVENTO_ANIMAR";
		
		//private var masa:Number;
		
		private var ancho:Number;
		private var alto:Number;
				
		private var vx:Number;
		private var vy:Number;		
		
		/*Distribucion de Aristas
		      0  
			  -
		  3 |   | 1
			  -
			  2		
		*/
		
		private var aristas:Array;
		
		public var xReal,yReal:Number;
		
		private var cuerpoColisionante:Cuerpo;//Este es el cuerpo contra el cual choco.
		
				
		public function Cuerpo (xx:Number, yy:Number, velx:Number, vely:Number, unAncho:Number, unAlto:Number)
		{
			xReal=xx;
			yReal=yy;			
			
			ancho=unAncho;
			alto=unAlto;
			
			vx=velx;
			vy=vely;
			
			aristas=new Array ();			
			cargarAristas ();
		}
		
		public function cargarAristas ():void
		{
			var arista0:Arista=new Arista(xReal,yReal,xReal+ancho,yReal,this);
			var arista1:Arista=new Arista(xReal+ancho,yReal,xReal+ancho,yReal+alto,this);
			var arista2:Arista=new Arista(xReal,yReal+alto,xReal+ancho,yReal+alto,this);
			var arista3:Arista=new Arista(xReal,yReal,xReal,yReal+alto,this);
			aristas.push(arista0);
			aristas.push(arista1);
			aristas.push(arista2);
			aristas.push(arista3);
		}
		
		public function modificarSize (unAncho:Number, unAlto:Number)
		{
			ancho=unAncho;
			alto=unAlto;
			aristas=new Array ();
			cargarAristas ();
		}		
		
		public function calcularEfectosColision (unaColision:Colision):void
		{			
			cuerpoColisionante = unaColision.getOtroCuerpo(this);
			var tipoColision:Number = unaColision.getTipoColision(this);
		
			//trace ("tipoColision="+tipoColision);
		/*
			var dt:Number = 0.0001;
		
			switch (tipoColision) {
				case 0:
					if (vy!=0)
					{
						vy=-vy;						
						yReal+=dt*vy;
					}
				break;
				
				case 1:
					if (vx!=0)
					{
						vx=-vx;
						xReal-=dt*vx;
					}
				break;
				
				case 2:
					if (vy!=0)
					{
						vy=-vy;
						yReal-=dt*vy;
					}
				break;
				
				case 3:
					if (vx!=0)
					{
						vx=-vx;
						xReal+=dt*vx;
					}
				break;
				
				case -1:
					trace ("ERROR en Cuerpo.calcularEfectosColision");
				break;
			}
		*/
		
			dispatchEvent(new Event(Cuerpo.EVENTO_COLISION));
			
			return;
		}
		
		public function puntoMedioX ():Number
		{
			return xReal+ancho/2;
		}
		
		public function puntoMedioY ():Number
		{
			return yReal+alto/2;
		}
		
		public function distanciaCuadrada (otroCuerpo:Cuerpo):Number //Devuelve la distancia^2 para ahorrar calculo
		{
			var xx,yy:Number;
			xx=this.puntoMedioX()-otroCuerpo.puntoMedioX();
			yy=this.puntoMedioY()-otroCuerpo.puntoMedioY();
			return (xx*xx+yy*yy);
		}
		
		public function colisionPermitida (otroCuerpo:Cuerpo):Boolean
		{
			return true;
		}
		
		public function animarHasta (unTiempo:Number):void // milisegundos
		{						
			xReal+=Number(vx*unTiempo/1000);
			yReal+=Number(vy*unTiempo/1000);
			//dispatchEvent(new Event(Cuerpo.EVENTO_ANIMAR));
		}
		
		private function verticeIncluidoMarco(x0:int, y0:int, p0x:int, p0y:int, p1x:int, p1y:int, p2x:int, p2y:int, p3x:int, p3y:int):Boolean
		{
			return ((x0>=p0x)&&(x0<=p1x) && (y0>=p0y)&&(y0<=p2y));
		}
		
		public function verticeDentroMarcoPresenteFuturo (x0:Number, y0:Number):Boolean
		{
			var p0x:int = 0;
			var p0y:int = 0;
				//----
			var p1x:int = 0;
			var p1y:int = 0;
				//----
			var p2x:int = 0;
			var p2y:int = 0;
				//----
			var p3x:int = 0;
			var p3y:int = 0;
			//----
			if ((vx>=0)&&(vy>=0))
			{
				p0x = this.xReal;
				p0y = this.yReal;
				//----
				p1x = this.xReal+ancho+vx*LineaTiempo.tiempoCompleto/1000;
				p1y = this.yReal;
				//----
				p2x = this.xReal+ancho+vx*LineaTiempo.tiempoCompleto/1000;
				p2y = this.yReal+alto+vy*LineaTiempo.tiempoCompleto/1000;
				//----
				p3x = this.xReal;
				p3y = this.yReal+alto+vy*LineaTiempo.tiempoCompleto/1000;			
			}
			else if ((vx<0)&&(vy>=0))
			{
				p0x = this.xReal+vx*LineaTiempo.tiempoCompleto/1000;
				p0y = this.yReal;
				//----
				p1x = this.xReal+ancho;
				p1y = this.yReal;
				//----
				p2x = this.xReal+ancho;
				p2y = this.yReal+alto+vy*LineaTiempo.tiempoCompleto/1000;
				//----
				p3x = this.xReal+vx*LineaTiempo.tiempoCompleto/1000;
				p3y = this.yReal+alto+vy*LineaTiempo.tiempoCompleto/1000;
			}
			else if ((vx<0)&&(vy<0))
			{
				p0x = this.xReal+vx*LineaTiempo.tiempoCompleto/1000;
				p0y = this.yReal+vy*LineaTiempo.tiempoCompleto/1000;
				//----
				p1x = this.xReal+ancho;
				p1y = this.yReal+vy*LineaTiempo.tiempoCompleto/1000;
				//----
				p2x = this.xReal+ancho;
				p2y = this.yReal+alto;
				//----
				p3x = this.xReal+vx*LineaTiempo.tiempoCompleto/1000;
				p3y = this.yReal+alto;
			}
			else if ((vx>=0)&&(vy<0))
			{
				p0x = this.xReal;
				p0y = this.yReal+vy*LineaTiempo.tiempoCompleto/1000;
				//----
				p1x = this.xReal+ancho+vx*LineaTiempo.tiempoCompleto/1000;
				p1y = this.yReal+vy*LineaTiempo.tiempoCompleto/1000;
				//----
				p2x = this.xReal+ancho+vx*LineaTiempo.tiempoCompleto/1000;
				p2y = this.yReal+alto;
				//----
				p3x = this.xReal;
				p3y = this.yReal+alto;
			}
			//----
			return verticeIncluidoMarco(x0,y0,p0x,p0y,p1x,p1y,p2x,p2y,p3x,p3y);
			
		}
		
		public function getEsquinas ():Array
		{
			var retArray:Array = new Array();
			var vertice:Vertice2D = null;
			//----
			vertice = new Vertice2D(xReal,yReal);
			retArray.push(vertice);
			//----
			vertice = new Vertice2D(xReal+ancho,yReal);
			retArray.push(vertice);
			//----
			vertice = new Vertice2D(xReal+ancho,yReal+alto);
			retArray.push(vertice);
			//----
			vertice = new Vertice2D(xReal+ancho,yReal);
			retArray.push(vertice);
			
			return retArray;			
		}
		
		public function colisionCuadrada (otroCuerpo:Cuerpo):Boolean
		{
			var ret:Boolean = false;
			var i:int = 0;
			var currentVertice:Vertice2D = null;
			var vertices:Array = getEsquinas();
			while ((!ret)&&(i!=4))
			{
				currentVertice=vertices[i];
				ret = otroCuerpo.verticeDentroMarcoPresenteFuturo(currentVertice.x,currentVertice.y);
				i++;
			}
			return ret;
		}
		
		public function seColisionan (otroCuerpo:Cuerpo):Colision
		{
			var i,j:Number;
			var colisionX:Colision=null;
			var colisionMenor:Colision=null;
			//----
			var ret:Boolean = true;
			ret=colisionCuadrada(otroCuerpo);
			if (ret==false)
			{
				ret=otroCuerpo.colisionCuadrada(this);
			}
			if (ret==false)
			{
				return null;
			}
			else
			{
				trace ("Colision Cuadrada.");
			}
			/*----*/
			
			if ( (! this.colisionPermitida(otroCuerpo)) || (! otroCuerpo.colisionPermitida(this)) )
			{
				return null;
			}			

			for (j=0;j<=3;j++)
			for (i=0;i<=3;i++)
			{				
				if (Arista(this.aristas[j]).tipo()==Arista(otroCuerpo.aristas[i]).tipo())
				{					
					colisionX=Arista(this.aristas[j]).seColisionan (Arista(otroCuerpo.aristas[i]),otroCuerpo);					
				}
				if (colisionMenor==null) colisionMenor=colisionX;
				if (colisionX!=null)
				{
					if (colisionMenor.tiempoColision>colisionX.tiempoColision)
					{
						colisionMenor=colisionX;
					}
				}
			}
			return colisionMenor;
		}		
		
		public function getAncho ():Number
		{
			return ancho;
		}
		
		public function getAlto ():Number
		{
			return alto;
		}
		
		public function getNumeroArista (unaArista:Arista):Number
		{
			var i:Number = 0;
			var encontrado:Boolean = false;
			while ((i<=3) && (! encontrado))
			{
				if (Arista(aristas[i])==unaArista)
				{
					encontrado = true;
				} 
				else
				{					
					i++;
				}
			}
			
			if (encontrado)
			{
				return i;
			}
			else
			{
				return -1;
			}
		}
		
		public function destroy ():void
		{			
			return;
		}		
		
		public function setVX (velX:Number)
		{
			//trace ("Cuerpo.moverX");
			vx = velX;
			Cuerpos.getInstancia().actualizarColision();
			return;
		}
		
		public function setVY (velY:Number)
		{
			//trace ("Cuerpo.moverY");
			vy = velY;
			Cuerpos.getInstancia().actualizarColision();
			return;
		}		
		
		public function getVX():Number
		{
			return vx;
		}
		
		public function getVY():Number
		{
			return vy;
		}
		
		
		public function getCuerpoColisionante ():Cuerpo
		{
			return cuerpoColisionante;
		}

	}
}